package user

import (
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/unknwon/com"
	"gorm.io/gorm"
	"likeadmin/client/schemas/req"
	"likeadmin/client/schemas/resp"
	"likeadmin/config"
	"likeadmin/core"
	"likeadmin/core/response"
	"likeadmin/model/client"
	"likeadmin/util"
	"strconv"
	"strings"
	"time"
)

// ISystemAuthAdminService 客户端用户相关业务接口定义
type ISystemAuthAdminService interface {
	// FindByUsername 根据设备ID查找用户
	FindByUsername(username string) (admin client.ClientUser, err error)

	// CacheAdminUserByUid 将指定ID的用户信息缓存到Redis中
	CacheAdminUserByUid(id uint) (err error)

	// Self 获取当前登录用户的详细信息
	Self(c *gin.Context, adminId uint) (res resp.ClientUserSelfOneResp, e error)

	// DramaList 分页获取短剧列表
	DramaList(adminId uint, page int, limit int) (res response.PageResp, e error)

	// DramaLook 观看某个剧集视频，并判断是否需要购买
	DramaLook(adminId uint, lookReq req.DramaLookReq) (res resp.DramaLookResp, e error)

	// SeriesList 分页获取某部短剧的所有剧集列表
	SeriesList(adminId uint, page int, limit int, req req.SeriesReq) (res response.PageSeriesResp, e error)

	// RechargeGear 获取所有可用的充值档位配置
	RechargeGear(adminId uint) (res []resp.RechargeGearResp, e error)

	// ReadRecords 获取用户的观看历史记录
	ReadRecords(adminId uint) (res []resp.ReadRecordsResp, e error)

	// PaySend 发起支付请求并创建订单
	PaySend(c *gin.Context, adminId uint, sendReq req.PaySendReq) (res interface{}, e error)

	// PayCall 支付回调处理逻辑
	PayCall(c *gin.Context, notifyReq req.PayNotifyReq) (res string, e error)

	// OrderIsPay 查询订单是否已支付
	OrderIsPay(c *gin.Context, payReq req.OrderIsPayReq) (res resp.Orders, e error)

	// OrderList 分页获取用户的充值订单列表
	OrderList(adminId uint, page int, limit int) (res response.PageResp, e error)

	// ConsumList 分页获取用户的消费记录（即购买过的剧集）
	ConsumList(adminId uint, page int, limit int) (res response.PageResp, e error)
}

// NewClientService 初始化客户端用户服务实例
func NewClientService(db *gorm.DB) ISystemAuthAdminService {
	// 初始化全局队列服务（如果尚未初始化）
	queueService := util.NewQueueService(core.Redis)
	return &clientUserService{
		db:           db,
		queueService: queueService, // 注入队列服务
	}
}

// clientUserService 实现ISystemAuthAdminService接口的具体结构体
type clientUserService struct {
	db           *gorm.DB
	queueService *util.QueueService // 添加队列服务字段
}

// FindByUsername 根据设备ID查找用户
func (adminSrv clientUserService) FindByUsername(username string) (admin client.ClientUser, err error) {
	err = adminSrv.db.Where("device_id = ?", username).Limit(1).First(&admin).Error
	return
}

// Self 获取管理员自身信息，并根据来源、地区、时间等条件计算跳转逻辑和展示内容
func (adminSrv clientUserService) Self(c *gin.Context, adminId uint) (res resp.ClientUserSelfOneResp, e error) {
	// 查询未被删除的管理员信息
	var clientUser client.ClientUser
	err := adminSrv.db.Where("id = ? AND is_delete = ?", adminId, 0).Limit(1).First(&clientUser).Error
	if e = response.CheckErrDBNotRecord(err, "Self First err"); e != nil {
		return
	}

	var selfOneResp resp.ClientUserSelfOneResp
	response.Copy(&selfOneResp, clientUser)
	selfOneResp.Avatar = util.UrlUtil.ToAbsoluteUrl(clientUser.Avatar)

	// 默认设置短剧和系列ID以及跳转类型
	selfOneResp.DramaId = "1001"
	selfOneResp.SeriesId = "1001001"
	selfOneResp.IsJump = 3 // [1=短剧, 2=工具 3=小说]

	// 查询该用户的来源信息，用于判断是否需要审核或进行区域屏蔽
	var source client.Source
	err = adminSrv.db.Model(&client.Source{}).Where("source_id = ? AND package_name = ?", clientUser.SourceId, clientUser.PackageName).Limit(1).First(&source).Error

	var topNum uint8

	if err == nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		selfOneResp.DramaId = source.DramaId
		selfOneResp.SeriesId = source.SeriesId
		topNum = 1
		// 如果处于审核状态，则跳转到小说页面
		if source.IsAudit == 1 {
			selfOneResp.IsJump = 3
			topNum = 2
		} else {
			selfOneResp.IsJump = 1
			if selfOneResp.IsJump == 1 {
				topNum = 3
			}
		}
	}

	// 检查当前城市是否在屏蔽地区列表中
	if selfOneResp.IsJump == 1 {
		// 检查当前城市是否在屏蔽地区列表中
		var black bool
		if len(source.Areas) == 0 {
			black = util.FilterUtil.City([]string{}, clientUser.CityInfo)
		} else {
			black = util.FilterUtil.City(strings.Split(source.Areas, "|"), clientUser.CityInfo)
		}

		core.Logger.Error(fmt.Sprintf("用户id：%v -  城市%v  - black：%v", clientUser.ID, clientUser.CityInfo, black))
		// 如果命中屏蔽规则，则跳转至工具页面
		if black == false {
			topNum = 6
			selfOneResp.IsJump = 3
		}
	}

	// 如果创建时间跟现在的时间在30秒内，则为新用户，不更新跳转信息
	if (time.Now().Unix() - clientUser.CreateTime) < 30 {
		// 更新登录信息
		_ = adminSrv.db.Model(&client.ClientUser{}).Where("id = ?", clientUser.ID).Select("is_jump").Updates(
			client.ClientUser{
				IsJump: selfOneResp.IsJump,
			}).Error
		topNum = 10
	} else {
		// 如果不是新用户，使用原来的跳转信息
		oldIsJump := selfOneResp.IsJump
		selfOneResp.IsJump = clientUser.IsJump
		core.Logger.Error(fmt.Sprintf("老用户：%d  跳转类型为：%d  检测跳转类型为：%d  命中topNum：%d, 短剧编号%v, 剧集编号%v", selfOneResp.ID, selfOneResp.IsJump, oldIsJump, topNum, selfOneResp.DramaId, selfOneResp.SeriesId))
	}

	// 如果是黑名单用户，则跳转到小说页面
	if clientUser.IsBlack == 1 {
		topNum = 9
		selfOneResp.IsJump = 3
	}

	// 如果是腾讯的地址，跳转工具
	if strings.Contains(clientUser.CityInfo, "腾讯") {
		topNum = 7
		selfOneResp.IsJump = 2 // [1=短剧, 2=工具 3=小说]
	}
	// 如果是PC微信浏览器打开，则统一跳转到工具页面
	if clientUser.Provider == "microsoft" || clientUser.Provider == "Android" || clientUser.Provider == "devtools" {
		topNum = 8
		selfOneResp.IsJump = 2
	}

	if selfOneResp.IsJump == 2 || selfOneResp.IsJump == 3 {
		core.Logger.Error(fmt.Sprintf("用户%d ：跳转逻辑：跳转类型为：%d,命中topNum：%d, 短剧编号%v, 剧集编号%v", selfOneResp.ID, selfOneResp.IsJump, topNum, selfOneResp.DramaId, selfOneResp.SeriesId))
	}

	selfOneResp.Nickname = clientUser.Nickname + com.ToStr(selfOneResp.ID)

	return selfOneResp, nil
}

// DramaList 分页获取短剧列表
func (adminSrv clientUserService) DramaList(adminId uint, page, limit int) (res response.PageResp, e error) {
	// 默认只运行六部
	limit = 6
	offset := (page - 1) * limit

	// 查询短剧列表
	var dramas []client.Drama
	var count int64
	err := adminSrv.db.Model(&client.Drama{}).Where("status = ?", 1).Count(&count).Error
	if e = response.CheckErrDBNotRecord(err, "DramaList Count err"); e != nil {
		return
	}

	err = adminSrv.db.Model(&client.Drama{}).Where("status = ?", 1).
		Order("create_time desc").
		Limit(limit).
		Offset(offset).
		Find(&dramas).Error

	if e = response.CheckErrDBNotRecord(err, "dramas Find err"); e != nil {
		return
	}

	// 转换为响应结构体
	var dramaResp []resp.DramaResp
	response.Copy(&dramaResp, dramas)

	// 处理封面图URL
	for i := range dramaResp {
		dramaResp[i].CoverUrl = util.UrlUtil.ToAbsoluteUrl(dramaResp[i].CoverUrl)
	}

	return response.PageResp{
		PageNo:   page,
		PageSize: limit,
		Count:    count,
		Lists:    dramaResp,
	}, nil
}

// DramaLook 观看某个剧集视频，并判断是否需要购买
func (adminSrv clientUserService) DramaLook(adminId uint, lookReq req.DramaLookReq) (res resp.DramaLookResp, e error) {
	var dramaLookResp resp.DramaLookResp
	// 短剧数据
	dramaLookResp.DramaId = lookReq.DramaId
	dramaLookResp.SeriesId = lookReq.SeriesId

	// 查询短剧信息
	var drama client.Drama
	err := adminSrv.db.Model(&client.Drama{}).Where("drama_id = ?", lookReq.DramaId).Limit(1).First(&drama).Error
	if e = response.CheckErrDBNotRecord(err, "drama First err！"); e != nil {
		return
	}

	// 查询剧集信息
	var dramaSeries client.DramaSeries
	err = adminSrv.db.Model(&client.DramaSeries{}).Where("drama_id = ? AND series_id = ?", lookReq.DramaId, lookReq.SeriesId).Limit(1).First(&dramaSeries).Error
	if e = response.CheckErrDBNotRecord(err, "dramaSeries First err！"); e != nil {
		return
	}

	// 查询用户信息
	var clientUser client.ClientUser
	err = adminSrv.db.Model(&client.ClientUser{}).Where("id = ? AND is_delete = ?", adminId, 0).Limit(1).First(&clientUser).Error
	if e = response.CheckErrDBNotRecord(err, "clientUser First err！"); e != nil {
		return
	}

	// 更新阅读记录
	adminSrv.updateReadRecords(clientUser, dramaLookResp, drama, dramaSeries)

	// 用户数据
	dramaLookResp.CoinBuy = clientUser.CoinBuy
	dramaLookResp.CoinGift = clientUser.CoinGift

	// 如果是VIP用户或剧集免费，无需购买
	if clientUser.UserType == 2 || dramaSeries.IsVip == 0 {
		dramaLookResp.IsBuy = 1
		dramaLookResp.VideoUrl = util.UrlUtil.ToAbsoluteUrl(dramaSeries.VideoUrl)
		return dramaLookResp, nil
	}

	// 检查用户是否已经购买
	isPurchased, err := adminSrv.checkIfPurchased(adminId, lookReq.DramaId, lookReq.SeriesId)
	if e = response.CheckErrDBNotRecord(err, "Check purchase status err"); e != nil {
		return
	}

	if isPurchased {
		dramaLookResp.IsBuy = 1
		dramaLookResp.VideoUrl = util.UrlUtil.ToAbsoluteUrl(dramaSeries.VideoUrl)
		return dramaLookResp, nil
	}

	// 检查用户是否有足够的金币购买
	totalCoins := clientUser.CoinBuy + clientUser.CoinGift
	if totalCoins >= drama.Money {
		// 扣除金币
		needDeduct := drama.Money
		giftDeduct := uint(0)
		buyDeduct := uint(0)

		// 优先扣除赠送金币
		if clientUser.CoinGift >= needDeduct {
			giftDeduct = needDeduct
		} else {
			giftDeduct = clientUser.CoinGift
			buyDeduct = needDeduct - giftDeduct
		}

		// 更新用户金币余额
		err = adminSrv.db.Model(&client.ClientUser{}).Where("id = ?", adminId).Updates(map[string]interface{}{
			"coin_buy":  clientUser.CoinBuy - buyDeduct,
			"coin_gift": clientUser.CoinGift - giftDeduct,
		}).Error
		if e = response.CheckErrDBNotRecord(err, "Update user coins err"); e != nil {
			return
		}

		dramaLookResp.IsBuy = 1
		dramaLookResp.VideoUrl = util.UrlUtil.ToAbsoluteUrl(dramaSeries.VideoUrl)
		dramaLookResp.CoinBuy = clientUser.CoinBuy - buyDeduct
		dramaLookResp.CoinGift = clientUser.CoinGift - giftDeduct

		// 更新阅读记录
		adminSrv.updateReadRecords(clientUser, dramaLookResp, drama, dramaSeries)

	} else {
		// 金币不足
		dramaLookResp.IsBuy = 0
		dramaLookResp.NeedCoins = drama.Money - totalCoins
	}

	return dramaLookResp, nil
}

// SeriesList 分页获取某部短剧的所有剧集列表
func (adminSrv clientUserService) SeriesList(adminId uint, page, limit int, req req.SeriesReq) (res response.PageSeriesResp, e error) {
	offset := (page - 1) * limit

	// 查询短剧信息
	var drama client.Drama
	err := adminSrv.db.Model(&client.Drama{}).Where("drama_id = ?", req.DramaId).Limit(1).First(&drama).Error
	if e = response.CheckErrDBNotRecord(err, "Drama First err"); e != nil {
		return
	}

	// 查询剧集列表
	var dramaSeries []client.DramaSeries
	var count int64
	err = adminSrv.db.Model(&client.DramaSeries{}).Where("drama_id = ?", req.DramaId).Count(&count).Error
	if e = response.CheckErrDBNotRecord(err, "DramaList Count err"); e != nil {
		return
	}

	err = adminSrv.db.Model(&client.DramaSeries{}).Where("drama_id = ?", req.DramaId).
		Order("create_time desc").
		Limit(limit).
		Offset(offset).
		Find(&dramaSeries).Error
	if e = response.CheckErrDBNotRecord(err, "dramaSeries Find err"); e != nil {
		return
	}

	// 查询用户已购买的剧集记录
	var readRecords []client.ReadRecords
	err = adminSrv.db.Model(&client.ReadRecords{}).Where("uid = ? AND drama_id = ? AND money > ?", adminId, req.DramaId, 0).Find(&readRecords).Error
	if e = response.CheckErrDBNotRecord(err, "readRecords Find err"); e != nil {
		return
	}

	// 转换为响应结构体
	var dramaResp []resp.DramaSeriesResp
	response.Copy(&dramaResp, dramaSeries)

	// 创建已购买剧集的映射，提高查找效率
	purchasedSeries := make(map[string]bool)
	for _, record := range readRecords {
		purchasedSeries[record.SeriesId] = true
	}

	// 处理剧集信息
	for i := range dramaResp {
		dramaResp[i].VideoUrl = util.UrlUtil.ToAbsoluteUrl(dramaResp[i].VideoUrl)

		// 如果用户已购买该剧集，设置为免费
		if purchasedSeries[dramaResp[i].SeriesId] {
			dramaResp[i].IsVip = 0
		}
	}

	return response.PageSeriesResp{
		PageNo:        page,
		PageSize:      limit,
		Count:         count,
		IsCompleted:   drama.IsCompleted,
		TotalEpisodes: drama.TotalEpisodes,
		HeatValue:     drama.HeatValue,
		Money:         drama.Money,
		Title:         drama.Title,
		Description:   drama.Description,
		CoverUrl:      util.UrlUtil.ToAbsoluteUrl(drama.CoverUrl),
		IsCollect:     1,
		Lists:         dramaResp,
	}, nil
}

// RechargeGear 获取所有可用的充值档位配置
func (adminSrv clientUserService) RechargeGear(adminId uint) (res []resp.RechargeGearResp, e error) {

	var TID uint
	TID = 1
	var clientUser client.ClientUser
	err := adminSrv.db.Where("id = ?", adminId).Limit(1).First(&clientUser).Error
	if e = response.CheckErrDBNotRecord(err, "RechargeGear clientUser First err！"); e != nil {
		TID = 1
	} else {
		var source client.Source
		err = adminSrv.db.Model(&client.Source{}).Where("source_id = ? AND package_name = ?", clientUser.SourceId, clientUser.PackageName).Limit(1).First(&source).Error
		if e = response.CheckErrDBNotRecord(err, "Source First err！"); e == nil {
			if source.GearType > 0 {
				TID = source.GearType
			}
		}
	}

	// 查询充值档位信息
	var rechargeGears []client.RechargeGear
	err = adminSrv.db.Model(&client.RechargeGear{}).Where("t_id = ? AND status = ?", TID, 1).Order("sort asc").
		Find(&rechargeGears).Error
	if e = response.CheckErrDBNotRecord(err, "rechargeGears First err"); e != nil {
		return
	}

	// 转换为响应结构体
	var rechargeGearResp []resp.RechargeGearResp
	response.Copy(&rechargeGearResp, rechargeGears)

	gearSigns := util.ConfigUtil.GearSigns()
	for i, gearResp := range rechargeGearResp {

		if gearResp.Sign != 0 {
			rechargeGearResp[i].SignName = gearSigns[gearResp.Sign]
		}

	}

	return rechargeGearResp, nil
}

// ReadRecords 获取用户的观看历史记录
func (adminSrv clientUserService) ReadRecords(adminId uint) (res []resp.ReadRecordsResp, e error) {
	// 查询用户的观看记录，按最后观看时间倒序排列，并按剧集分组
	var readRecords []client.ReadRecords
	err := adminSrv.db.Model(&client.ReadRecords{}).Where("uid = ?", adminId).Order("last_time desc").
		Group("drama_id").
		Find(&readRecords).Error
	if e = response.CheckErrDBNotRecord(err, "readRecords find err"); e != nil {
		return
	}

	// 收集所有剧集ID
	dramaIds := make([]string, len(readRecords))
	for i, record := range readRecords {
		dramaIds[i] = record.DramaId
	}

	// 批量查询剧集信息
	var dramas []client.Drama
	if len(dramaIds) > 0 {
		err = adminSrv.db.Model(&client.Drama{}).Where("drama_id IN ?", dramaIds).Find(&dramas).Error
		if e = response.CheckErrDBNotRecord(err, "Drama Find err"); e != nil {
			return
		}
	}

	// 创建剧集ID到剧集信息的映射
	dramaMap := make(map[string]client.Drama)
	for _, drama := range dramas {
		dramaMap[drama.DramaId] = drama
	}

	// 转换为响应结构体
	readRecordsResp := make([]resp.ReadRecordsResp, len(readRecords))
	for i, record := range readRecords {
		drama, exists := dramaMap[record.DramaId]
		if !exists {
			continue
		}

		readRecordsResp[i] = resp.ReadRecordsResp{
			ID:         record.ID,
			SeriesId:   record.SeriesId,
			DramaId:    record.DramaId,
			Title:      drama.Title,
			CoverUrl:   util.UrlUtil.ToAbsoluteUrl(drama.CoverUrl),
			LastTime:   record.LastTime,
			StartTime:  record.StartTime,
			CreateTime: record.CreateTime,
			UpdateTime: record.UpdateTime,
		}
	}

	return readRecordsResp, nil
}

// PaySend 发起支付请求并创建订单
func (adminSrv clientUserService) PaySend(c *gin.Context, adminId uint, sendReq req.PaySendReq) (res interface{}, e error) {
	// 查询用户信息
	var clientUser client.ClientUser
	err := adminSrv.db.Where("id = ? AND is_delete = ?", adminId, 0).Limit(1).First(&clientUser).Error
	if e = response.CheckErrDBNotRecord(err, "Self First err"); e != nil {
		return
	}

	// 查询充值档位信息
	var rechargeGear client.RechargeGear
	err = adminSrv.db.Model(&client.RechargeGear{}).Where("id = ? AND status = ?", sendReq.GearId, 1).First(&rechargeGear).Error
	if e = response.CheckErrDBNotRecord(err, "RechargeGear First err"); e != nil {
		return
	}

	// 根据包名获取应用配置的支付 。调用service AppConfigCache 获取配置
	appConfig, err := util.ConfigUtil.AppConfigCache(adminSrv.db, clientUser.PackageName)
	if e = response.CheckErrDBNotRecord(err, "获取app配置 err"); e != nil {
		return
	}

	configFlags := strings.Split(appConfig.PayFlag, "-")
	// 过滤空字符串，避免因前导或尾随分隔符产生的空元素
	var validFlags []string
	for _, flag := range configFlags {
		if strings.TrimSpace(flag) != "" {
			validFlags = append(validFlags, flag)
		}
	}
	if len(validFlags) == 0 {
		e = response.AssertArgumentError.Make("未配置有效的支付标识")
		return
	}

	// 随机选择一个配置标识
	randomIndex := util.ToolsUtil.RandomInt(len(validFlags))

	// 获取支付配置
	payConfig, err := adminSrv.PayConfigCache(validFlags[randomIndex])
	if e = response.CheckErrDBNotRecord(err, "获取配置 err"); e != nil {
		return
	}

	// 创建订单记录
	orders := client.Orders{
		Channel:        clientUser.Channel,
		Uid:            clientUser.ID,
		CreaterID:      clientUser.CreaterID,
		SourceId:       clientUser.SourceId,
		AccountId:      clientUser.AccountId,
		SourceIdActive: clientUser.SourceIdActive,
		UserCreateTime: clientUser.CreateTime,
		UserActiveTime: clientUser.ActiveTime,
		PackageName:    clientUser.PackageName,
		OutNo:          util.ToolsUtil.MakeOrderNo(),
		PayType:        "MINIAPP_WEIXIN",
		PayWay:         "WEIXIN",
		Type:           rechargeGear.Type,
		Buy:            rechargeGear.Buy,
		Gift:           rechargeGear.Gift,
		VipDays:        rechargeGear.VipDays,
		GearId:         rechargeGear.ID,
		Money:          rechargeGear.Price,
		IsPay:          0,
		SeriesId:       sendReq.SeriesId,
		DramaId:        sendReq.DramaId,
		Status:         0,
		PayFlag:        payConfig.Flag,
		PayIp:          util.IpUtil.GetRealIp(c),
		PayUa:          strings.ToLower(c.Request.Header.Get("User-Agent")),
	}

	err = adminSrv.db.Model(&client.Orders{}).Create(&orders).Error
	if err != nil {
		e = response.CheckErrDBNotRecord(err, "orders Create err")
		return
	}

	// 准备支付参数
	payParams := map[string]interface{}{
		"merAccount":  payConfig.MerAccount,
		"merNo":       payConfig.MerNo,
		"time":        com.ToStr(time.Now().Unix()),
		"orderId":     orders.OutNo,
		"amount":      com.ToStr(orders.Money),
		"product":     "购买" + appConfig.Title + "产品",
		"productDesc": "",
		"payWay":      orders.PayWay,
		"payType":     orders.PayType,
		"userIp":      orders.PayIp,
		"attach":      orders.OutNo + "--" + com.ToStr(clientUser.ID),
		"openId":      clientUser.DeviceId,
		"notifyUrl":   config.Config.PublicUrl + "/client/user/pay/notify/" + payConfig.Flag,
	}

	// 调起米花支付
	payResult := util.PaySend(payParams, payConfig.PrivateKey, payConfig.MerAccount)

	if payResult["code"] != "000000" {
		e = response.CheckErrDBNotRecord(errors.New("支付失败"), "支付失败")
		return
	}

	return payResult["data"], nil
}

// PayCall 米花支付回调处理逻辑
func (adminSrv clientUserService) PayCall(c *gin.Context, notifyReq req.PayNotifyReq) (res string, e error) {
	// 获取支付配置
	payConfig, err := adminSrv.PayConfigCache(notifyReq.Channel)
	if e = response.CheckErrDBNotRecord(err, "获取支付配置失败"); e != nil {
		return
	}

	// 解密支付回调数据
	decryptData, err := util.RsaDecrypt(notifyReq.Data, payConfig.PublicKey)
	if e = response.CheckErrDBNotRecord(err, "支付回调数据解密失败"); e != nil {
		return
	}

	// 解析解密后的JSON数据
	var payResult map[string]interface{}
	err = util.ToolsUtil.JsonToObj(decryptData, &payResult)
	if err != nil {
		e = response.CheckErrDBNotRecord(err, "解析支付结果失败")
		return
	}

	// 检查必要字段是否存在
	if payResult["orderStatus"] == nil || payResult["orderId"] == nil || payResult["bankOrderNo"] == nil {
		e = response.CheckErrDBNotRecord(errors.New("支付回调数据缺失必要字段"), "支付回调数据不完整")
		return
	}

	// 检查订单状态
	orderStatus, ok := payResult["orderStatus"].(string)
	if !ok {
		e = response.CheckErrDBNotRecord(errors.New("订单状态格式错误"), "订单状态解析失败")
		return
	}

	if orderStatus != "SUCCESS" {
		e = response.CheckErrDBNotRecord(errors.New("订单支付失败: "+orderStatus), "订单支付失败")
		return
	}

	// 获取订单号
	orderId, ok := payResult["orderId"].(string)
	if !ok || orderId == "" {
		e = response.CheckErrDBNotRecord(errors.New("订单号格式错误"), "订单号解析失败")
		return
	}

	// 商户系统交易单号
	bankOrderNo, ok := payResult["bankOrderNo"].(string)
	if !ok || bankOrderNo == "" {
		e = response.CheckErrDBNotRecord(errors.New("商户订单号格式错误"), "商户订单号解析失败")
		return
	}

	// 查找订单记录
	var order client.Orders
	err = adminSrv.db.Model(&client.Orders{}).Where("out_no = ? AND is_pay = ?", orderId, 0).First(&order).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			// 订单已处理或不存在，返回成功避免重复处理
			return "SUCCESS", nil
		}
		e = response.CheckErrDBNotRecord(err, "查询订单记录失败")
		return
	}

	// 开始事务处理
	tx := adminSrv.db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
			e = response.CheckErrDBNotRecord(errors.New("系统异常"), "支付回调处理异常")
		}
	}()

	// 更新订单状态
	err = tx.Model(&order).Updates(map[string]interface{}{
		"is_pay":           1,
		"mch_no":           bankOrderNo,
		"status":           1,
		"pay_time":         time.Now().Unix(),
		"user_active_time": time.Now().Unix(),
	}).Error
	if err != nil {
		tx.Rollback()
		e = response.CheckErrDBNotRecord(err, "更新订单状态失败")
		return
	}

	// 查找用户信息
	var user client.ClientUser
	err = tx.Model(&client.ClientUser{}).Where("id = ?", order.Uid).First(&user).Error
	if err != nil {
		tx.Rollback()
		e = response.CheckErrDBNotRecord(err, "查找用户信息失败")
		return
	}

	// 更新用户金币和VIP信息
	updates := map[string]interface{}{
		"coin_buy":         user.CoinBuy + order.Buy,
		"coin_gift":        user.CoinGift + order.Gift,
		"active_time":      time.Now().Unix(),
		"source_id_active": user.SourceId,
	}

	// 如果是会员充值，更新VIP信息
	if order.Type == 2 {
		updates["user_type"] = 2
		updates["vip_time"] = user.VipTime + int64(order.VipDays*24*3600)
	}

	err = tx.Model(&client.ClientUser{}).Where("id = ?", user.ID).Updates(updates).Error
	if err != nil {
		tx.Rollback()
		e = response.CheckErrDBNotRecord(err, "更新用户信息失败")
		return
	}

	// 提交事务
	err = tx.Commit().Error
	if err != nil {
		e = response.CheckErrDBNotRecord(err, "事务提交失败")
		return
	}

	err = adminSrv.queueService.AddOrderMessage(util.OrderMessage{
		Type:     "order",
		OrderID:  order.OutNo,
		DeviceId: user.DeviceId,
		Complete: true,
		Time:     time.Now(),
	}, 30)

	if err != nil {
		core.Logger.Errorf("添加订单消息到队列失败: %v", err)
	}

	return "SUCCESS", nil
}

// OrderIsPay 查询订单是否已支付
func (adminSrv clientUserService) OrderIsPay(c *gin.Context, payReq req.OrderIsPayReq) (res resp.Orders, err error) {
	var order client.Orders
	err = adminSrv.db.Model(&client.Orders{}).Where("out_no = ?", payReq.OrderId).Limit(1).First(&order).Error
	if e := response.CheckErrDBNotRecord(err, "order First err"); e != nil {
		return
	}

	var ordersResp resp.Orders
	response.Copy(&ordersResp, order)
	ordersResp.OrderId = order.OutNo

	return ordersResp, nil
}

// OrderList 分页获取用户的充值订单列表
func (adminSrv clientUserService) OrderList(adminId uint, page, limit int) (res response.PageResp, e error) {
	offset := (page - 1) * limit

	var count int64
	err := adminSrv.db.Model(&client.Orders{}).Where("uid = ?", adminId).Count(&count).Error
	if e = response.CheckErrDBNotRecord(err, "OrderList Count err"); e != nil {
		return
	}

	// 查询订单列表
	var orders []client.Orders
	err = adminSrv.db.Model(&client.Orders{}).Where("uid = ?", adminId).
		Order("create_time desc").
		Limit(limit).
		Offset(offset).
		Find(&orders).Error
	if e = response.CheckErrDBNotRecord(err, "orders Find err"); e != nil {
		return
	}

	// 转换为响应结构体
	var ordersResp []resp.OrderLists
	response.Copy(&ordersResp, orders)

	// 收集所有剧集ID
	dramaIds := make([]string, 0)
	for _, order := range ordersResp {
		if order.DramaId != "" {
			dramaIds = append(dramaIds, order.DramaId)
		}
	}

	// 批量查询剧集信息
	dramaMap := make(map[string]client.Drama)
	if len(dramaIds) > 0 {
		var dramas []client.Drama
		err = adminSrv.db.Model(&client.Drama{}).Where("drama_id IN ?", dramaIds).Find(&dramas).Error
		if err == nil {
			for _, drama := range dramas {
				dramaMap[drama.DramaId] = drama
			}
		}
	}

	// 处理剧集信息
	for i := range ordersResp {
		if drama, exists := dramaMap[ordersResp[i].DramaId]; exists {
			ordersResp[i].CoverUrl = util.UrlUtil.ToAbsoluteUrl(drama.CoverUrl)
			ordersResp[i].DramaId = drama.DramaId
			ordersResp[i].Title = drama.Title
			ordersResp[i].Description = drama.Description
		}
	}

	return response.PageResp{
		PageNo:   page,
		PageSize: limit,
		Count:    count,
		Lists:    ordersResp,
	}, nil
}

// ConsumList 分页获取用户的消费记录（即购买过的剧集）
func (adminSrv clientUserService) ConsumList(adminId uint, page, limit int) (res response.PageResp, e error) {
	offset := (page - 1) * limit

	var count int64
	err := adminSrv.db.Model(&client.ReadRecords{}).Where("uid = ? AND money > ?", adminId, 0).Count(&count).Error
	if e = response.CheckErrDBNotRecord(err, "ConsumList Count err"); e != nil {
		return
	}

	// 查询消费记录
	var readRecords []client.ReadRecords
	err = adminSrv.db.Model(&client.ReadRecords{}).Where("uid = ? AND money > ?", adminId, 0).
		Order("create_time desc").
		Limit(limit).
		Offset(offset).
		Find(&readRecords).Error
	if e = response.CheckErrDBNotRecord(err, "ConsumList Find err"); e != nil {
		return
	}

	// 转换为响应结构体
	var consumLists []resp.ReadRecordsResp
	response.Copy(&consumLists, readRecords)

	// 收集所有剧集ID
	dramaIds := make([]string, 0)
	for _, record := range readRecords {
		if record.DramaId != "" {
			dramaIds = append(dramaIds, record.DramaId)
		}
	}

	// 批量查询剧集信息
	dramaMap := make(map[string]client.Drama)
	if len(dramaIds) > 0 {
		var dramas []client.Drama
		err = adminSrv.db.Model(&client.Drama{}).Where("drama_id IN ?", dramaIds).Find(&dramas).Error
		if err == nil {
			for _, drama := range dramas {
				dramaMap[drama.DramaId] = drama
			}
		}
	}

	// 批量查询剧集信息
	dramaSeriesMap := make(map[string]client.DramaSeries)
	if len(dramaIds) > 0 {
		var dramaSeries []client.DramaSeries
		err = adminSrv.db.Model(&client.DramaSeries{}).Where("drama_id IN ?", dramaIds).Find(&dramaSeries).Error
		if err == nil {
			for _, series := range dramaSeries {
				dramaSeriesMap[series.SeriesId] = series
			}
		}
	}

	// 处理剧集信息
	for i := range consumLists {
		if drama, exists := dramaMap[consumLists[i].DramaId]; exists {
			consumLists[i].CoverUrl = util.UrlUtil.ToAbsoluteUrl(drama.CoverUrl)
			consumLists[i].DramaId = drama.DramaId
			consumLists[i].Title = drama.Title
		}
		if series, exists := dramaSeriesMap[consumLists[i].SeriesId]; exists {
			consumLists[i].Sort = series.Sort
		}
	}

	return response.PageResp{
		PageNo:   page,
		PageSize: limit,
		Count:    count,
		Lists:    consumLists,
	}, nil
}

/********* 内部使用 *********/

// PayConfigCache 缓存管理：从Redis中获取支付配置，如果不存在则从数据库加载并缓存
func (adminSrv clientUserService) PayConfigCache(flag string) (p client.PayConfigs, err error) {
	var payConfigs client.PayConfigs
	payFlagKey := config.ClientConfig.BackstagePayConfigSet + flag

	// 尝试从Redis获取
	s := util.RedisUtil.Get(payFlagKey)
	if s != "" {
		err = util.ToolsUtil.JsonToObj(s, &payConfigs)
		if err != nil {
			return
		}
		return payConfigs, nil
	}

	// 从数据库获取
	err = adminSrv.db.Model(&client.PayConfigs{}).Where("flag = ? AND status = ?", flag, 1).Limit(1).First(&payConfigs).Error
	if err != nil {
		return
	}

	// 存入Redis缓存
	str, err := util.ToolsUtil.ObjToJson(&payConfigs)
	if err != nil {
		return
	}

	util.RedisUtil.Set(payFlagKey, str, 60*60) // 缓存1小时

	return payConfigs, nil
}

// checkIfPurchased 检查用户是否已经购买剧集
func (adminSrv clientUserService) checkIfPurchased(userId uint, dramaId, seriesId string) (bool, error) {
	var record client.ReadRecords
	err := adminSrv.db.Where("uid = ? AND drama_id = ? AND series_id = ?", userId, dramaId, seriesId).
		First(&record).Error

	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return false, nil // 未找到记录，表示未购买
		}
		return false, err // 其他错误
	}

	// 如果记录存在且money大于0，则表示已购买
	return record.Money > 0, nil
}

// updateReadRecords 更新阅读记录
func (adminSrv clientUserService) updateReadRecords(clientUser client.ClientUser, dramaLook resp.DramaLookResp, drama client.Drama, dramaSeries client.DramaSeries) error {
	var record client.ReadRecords
	// 查找是否已有记录
	err := adminSrv.db.Where("uid = ? AND drama_id = ? AND series_id = ?", clientUser.ID, drama.DramaId, dramaSeries.SeriesId).First(&record).Error
	var money uint
	if dramaLook.IsBuy == 1 {
		money = drama.Money
	}
	now := time.Now().Unix()
	if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {

		// 创建新记录
		record = client.ReadRecords{
			Uid:            clientUser.ID,
			UserCreateTime: clientUser.CreateTime,
			SeriesId:       dramaSeries.SeriesId,
			DramaId:        drama.DramaId,
			Money:          money,
			LastTime:       now,
			StartTime:      now,
			CreateTime:     now,
			UpdateTime:     now,
		}
		return adminSrv.db.Create(&record).Error
	} else if err != nil {
		return err
	} else {
		// 更新用户金币和VIP信息
		updates := map[string]interface{}{
			"last_time":   now,
			"update_time": now,
		}

		if money > 0 {
			updates["money"] = money
		}
		// 更新现有记录
		return adminSrv.db.Model(&record).Updates(updates).Error
	}
}

// CacheAdminUserByUid 将指定ID的用户信息缓存到Redis中
func (adminSrv clientUserService) CacheAdminUserByUid(id uint) (err error) {
	var admin client.ClientUser
	err = adminSrv.db.Where("id = ?", id).Limit(1).First(&admin).Error
	if err != nil {
		return
	}
	str, err := util.ToolsUtil.ObjToJson(&admin)
	if err != nil {
		return
	}

	util.RedisUtil.HSet(config.ClientConfig.BackstageManageKey, strconv.FormatUint(uint64(admin.ID), 10), str, 0)

	return nil
}
